package com.netflix.maestro.models.signal;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.netflix.maestro.annotations.Nullable;
import com.netflix.maestro.models.api.SignalCreateRequest;
import com.netflix.maestro.models.error.Details;
import com.netflix.maestro.validations.MaestroNameConstraint;
import java.util.Map;
import lombok.Data;
import lombok.ToString;

/**
 * Signal instance data model.
 *
 * @author jun-he
 */
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonPropertyOrder(
    value = {
      "name",
      "seq_id",
      "instance_id",
      "params",
      "payload",
      "request_id",
      "request_time",
      "create_time"
    },
    alphabetic = true)
@Data
@ToString
public class SignalInstance {
  /** Name of the signal. */
  @MaestroNameConstraint private String name;

  /**
   * signal sequence id is generated after inserting into the table. Its value is always positive,
   * starting from 1. If not, it means this signal instance is a duplicate one.
   */
  private long seqId;

  /** Signal instance id is generated by the signal data. */
  private String instanceId;

  /** Indexed parameters used for matching, only support string and long values. */
  @Nullable private Map<String, SignalParamValue> params;

  /**
   * Map of key value pairs stored in the payload of the signal instance, which are not indexed for
   * matching. It is just for informational purposes and won't be used by Maestro engine.
   */
  @Nullable private Map<String, Object> payload;

  /** The time that the signal is announced. By default, it is request received time. */
  private long requestTime;

  /** The time that the signal instance is created. */
  private long createTime;

  /** Error details if the instance is not created, i.e. duplicate. */
  @JsonIgnore private Details details;

  /**
   * Convert a signal request to a signal instance (missing seq id). The sequence id will be set
   * later.
   */
  @JsonIgnore
  public static SignalInstance from(SignalCreateRequest request, String instanceId) {
    SignalInstance instance = new SignalInstance();
    instance.setName(request.getName());
    // seq_id is still unknown
    instance.setInstanceId(instanceId);
    instance.setParams(request.getParams());
    instance.setPayload(request.getPayload());
    instance.setRequestTime(request.getRequestTime());
    instance.setCreateTime(System.currentTimeMillis());
    return instance;
  }
}
